import { saveAs } from 'file-saver'
import { download } from '@/api/common'
import FSMessage from '@/utils/message'
import type { FormInstance } from 'element-plus'
/**
 * 图片质量压缩
 * @param file,file为不是数组的那个file，格式就是file的file,文件大小若小于300k，则不做压缩
 * @param quality, 压缩比例， 0.2-0.5之间效果最好，默认为0.52
 * @returns {Promise<unknown>|Promise<unknown[]>}， 返回值为Promise，所以使用方式为compressImg(file:any, 0.52).then((res:any)) => {res.file})
 */
export const compressImage = (
  file: any,
  quality = 0.52
): Promise<any> => {
  // parseInt((file.size / 1024).toFixed(2)), 单位kb
  console.log('开始压缩')
  let qualitys = 0.52
  const fileKBSize = parseInt((file.size / 1024).toFixed(2)) // 如果出了错或者功能不行，就把fileKBSize换成上面的parseInt
  if (fileKBSize < 1024) {
    // < 1MB
    qualitys = 0.85
  }
  if (5 * 1024 < fileKBSize) {
    qualitys = 0.92
  }
  if (quality) {
    qualitys = quality
  }
  if (file[0]) {
    return Promise.all(Array.from(file).map((e) => compressImage(e, qualitys))) // 如果是 file 数组返回 Promise 数组
  } else {
    return new Promise((resolve) => {
      if (fileKBSize < 300) {
        resolve({ file: file })
      } else {
        const reader = new FileReader() // 创建 FileReader
        // @ts-ignore
        reader.onload = ({ target: { result: src } }) => {
          const image = new Image() // 创建 img 元素
          image.onload = async () => {
            const canvas = document.createElement('canvas') // 创建 canvas 元素
            const context = canvas.getContext('2d')
            let targetWidth = image.width
            let targetHeight = image.height
            const originWidth = image.width
            const originHeight = image.height
            if (fileKBSize >= 1024 && fileKBSize <= 10 * 1024) {
              // 1MB < fileKBSize < 10M
              var maxWidth = 1600
              var maxHeight = 1600
              targetWidth = originWidth
              targetHeight = originHeight
              // 图片尺寸超过的限制
              if (originWidth > maxWidth || originHeight > maxHeight) {
                if (originWidth / originHeight > maxWidth / maxHeight) {
                  // 更宽，按照宽度限定尺寸
                  targetWidth = maxWidth
                  targetHeight = Math.round(
                    maxWidth * (originHeight / originWidth)
                  )
                } else {
                  targetHeight = maxHeight
                  targetWidth = Math.round(
                    maxHeight * (originWidth / originHeight)
                  )
                }
              }
            }
            if (10 * 1024 <= fileKBSize && fileKBSize <= 20 * 1024) {
              maxWidth = 1400
              maxHeight = 1400
              targetWidth = originWidth
              targetHeight = originHeight
              // 图片尺寸超过的限制
              if (originWidth > maxWidth || originHeight > maxHeight) {
                if (originWidth / originHeight > maxWidth / maxHeight) {
                  // 更宽，按照宽度限定尺寸
                  targetWidth = maxWidth
                  targetHeight = Math.round(
                    maxWidth * (originHeight / originWidth)
                  )
                } else {
                  targetHeight = maxHeight
                  targetWidth = Math.round(
                    maxHeight * (originWidth / originHeight)
                  )
                }
              }
            }
            canvas.width = targetWidth
            canvas.height = targetHeight
            // @ts-ignore
            context.clearRect(0, 0, targetWidth, targetHeight)
            // @ts-ignore
            context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
            const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
            const buffer = atob(canvasURL.split(',')[1])
            let length = buffer.length
            const bufferArray = new Uint8Array(new ArrayBuffer(length))
            while (length--) {
              bufferArray[length] = buffer.charCodeAt(length)
            }
            const miniFile = new File([bufferArray], file.name, {
              type: 'image/jpeg'
            })
            console.log(Number(fileKBSize), 'K压缩前')
            console.log(Number((miniFile.size / 1024).toFixed(2)), 'K压缩后')
            resolve({
              file: miniFile,
              origin: file,
              beforeSrc: src,
              afterSrc: canvasURL,
              beforeKB: Number(fileKBSize),
              afterKB: Number((miniFile.size / 1024).toFixed(2))
            })
          }
          // @ts-ignore
          image.src = src
        }
        reader.readAsDataURL(file)
      }
    })
  }
}

/**
 * 获取传入文件的后缀名
 * @param fileName 文件名
 * @returns 后缀名
 */
export const getSuffix = (fileName: string): string => {
  const splitedFileNames = fileName.split('.')
  return splitedFileNames[splitedFileNames.length - 1]
}

/**
 * 校验返回数据是否为blob
 * @param text axios返回的blob数据
 * @returns boolean
 */
export const validIsBlob = async (text): Promise<boolean> => {
  try {
    // @ts-ignore
    const text = await res.text()
    JSON.parse(text)
    return Promise.resolve(false)
  } catch (error) {
    return Promise.reject(true)
  }
}

/**
 * 文件下载，截取文件名，调用方法下载
 * @param url 可访问的服务器连接地址
 */
export const FSSaveAs = async (url: string) => {
  try {
    const splitList = url.split('/')
    const fileName = splitList[splitList.length - 1]
    const res = await download(fileName) as any
    const blob = new Blob([res])
    saveAs(blob, fileName)
  } catch (e) {
    console.log(e)
  }
}

/**
 * @breif: 重置表单，传入表单的ref
 * @param {FormInstance} formEl
 * @return {*}
 */
export const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}

/**
 * @breif: 校验表单
 * @param {FormInstance} formEl
 * @return {*}
 */
export const validateForm = (formEl: FormInstance | undefined) => {
  return new Promise((resolve, reject) => {
    if (!formEl) reject('formEl 为空')
    formEl.validate((valid, fields) => {
      if (valid) {
        resolve('校验成功')
      } else {
        reject(fields)
      }
    })
  })
}

/**
 * @breif: 递归函数，处理后端返回的数据成可展示成tree的数据
 * @param {*} menuChildren Array
 * @return {*}
 */
export const processMenuChildren = (menuChildren: any[]): any[] => {
  menuChildren.forEach(item => {
    item.label = item.meta.title
    item.value = item.menuId
    item.icon = item.meta.icon
    if (item.children?.length) {
      processMenuChildren(item.children)
    }
  })
  return menuChildren
}

/**
 * @breif: 将平铺数据根据 code 和 parentCode 构建成树形结构
 * @param {any[]} data 平铺的数据数组，每个元素需包含 code、parentCode、name 字段
 * @return {any[]} 返回树形结构数据，包含 children、value、label 字段
 */
export const buildTreeData = (data: any[]) => {
  const map = new Map();
  const result: any[] = [];

  // 创建映射，以code为key
  data.forEach((item) => {
    map.set(item.code, {
      ...item,
      children: [],
      value: item.code,
      label: item.name
    });
  });

  // 构建树形结构
  data.forEach((item) => {
    const node = map.get(item.code);
    if (item.parentCode && map.has(item.parentCode)) {
      const parent = map.get(item.parentCode);
      parent.children.push(node);
    } else {
      // 没有父节点的作为根节点
      result.push(node);
    }
  });

  return result;
};

/**
 * @breif: 字典类型转换成字典值
 * @param {string} value
 * @param {any} arr
 * @param {string} key
 * @return {*}
 */
export const mapKeyLabel = (target: string | number, arr: any[], key?: string, value?: string): string => {
  const dictKey = key || 'label'
  const dictVal = value || 'value'
  if (arr?.length) {
    const res = arr.find(item => item[dictVal] === target)
    if (res) {
      return res[dictKey]
    }
  }
  return '--'
}
